package org.jeecg.modules.pickOrder.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.constant.WarehouseConstant;
import org.jeecg.modules.basicSkuInfo.entity.BasicSkuInfo;
import org.jeecg.modules.basicSkuInfo.service.IBasicSkuInfoService;
import org.jeecg.modules.inOrder.entity.InOrder;
import org.jeecg.modules.inOrder.entity.InOrderDetail;
import org.jeecg.modules.inOrder.service.IInOrderDetailService;
import org.jeecg.modules.inOrder.service.IInOrderService;
import org.jeecg.modules.inventory.entity.InventoryInfo;
import org.jeecg.modules.inventory.service.IInventoryInfoService;
import org.jeecg.modules.pickOrder.entity.PickOrder;
import org.jeecg.modules.pickOrder.entity.PickOrderDetail;
import org.jeecg.modules.pickOrder.service.IPickOrderDetailService;
import org.jeecg.modules.pickOrder.service.IPickOrderService;
import org.jeecg.modules.pickOrder.vo.PickOrderPage;
import org.jeecg.modules.reportLabel.entity.ReportLabel;
import org.jeecg.modules.reportLabel.service.IReportLabelService;
import org.jeecg.modules.system.util.QRCodeUtil;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 理货管理
 * @Author: jeecg-boot
 * @Date: 2024-10-30
 * @Version: V1.0
 */
@Api(tags = "理货管理")
@RestController
@RequestMapping("/pickOrder/pickOrder")
@Slf4j
public class PickOrderController {
    @Autowired
    private IPickOrderService pickOrderService;
    @Autowired
    private IPickOrderDetailService pickOrderDetailService;
    @Autowired
    private IReportLabelService reportLabelService;
    @Autowired
    private IInventoryInfoService inventoryInfoService;
    @Autowired
    private IInOrderService inOrderService;
    @Autowired
    private IInOrderDetailService inOrderDetailService;
    @Autowired
    private IBasicSkuInfoService basicSkuInfoService;

    /**
     * 分页列表查询
     *
     * @param pickOrder
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    @AutoLog(value = "理货管理-分页列表查询")
    @ApiOperation(value = "理货管理-分页列表查询", notes = "理货管理-分页列表查询")
    @GetMapping(value = "/list")
    public Result<?> queryPageList(PickOrder pickOrder,
                                   @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                   @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                   HttpServletRequest req) {
        QueryWrapper<PickOrder> queryWrapper = QueryGenerator.initQueryWrapper(pickOrder, req.getParameterMap());
        queryWrapper.ne("status", WarehouseConstant.PickWarehouseTaskStaffEnum.DELETE.getCode());
        Page<PickOrder> page = new Page<PickOrder>(pageNo, pageSize);
        IPage<PickOrder> pageList = pickOrderService.page(page, queryWrapper);
        return Result.OK(pageList);
    }

    /**
     * 分页列表查询
     *
     * @param pickOrder
     * @param pageNo
     * @param pageSize
     * @param source    01：所有任务列表 02：过往任务列表
     * @param req
     * @return
     */
    @AutoLog(value = "理货管理-手持分页列表查询")
    @ApiOperation(value = "理货管理-手持分页列表查询", notes = "理货管理-手持分页列表查询")
    @GetMapping(value = "/appList")
    public Result<?> appList(PickOrder pickOrder,
                             @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                             @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                             @RequestParam(name = "source") String source,
                             HttpServletRequest req) {
        QueryWrapper<PickOrder> queryWrapper = QueryGenerator.initQueryWrapper(pickOrder, req.getParameterMap());
        if (Objects.equals(source, "01")) {
            queryWrapper.eq("status", WarehouseConstant.PickWarehouseTaskStaffEnum.RELEASE_END.getCode());
        } else if (Objects.equals(source, "02")) {
            LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            queryWrapper.eq("execute_name", sysUser.getUsername());
            queryWrapper.ne("status", WarehouseConstant.PickWarehouseTaskStaffEnum.DELETE.getCode());
        }
        queryWrapper.orderByAsc("FIELD(status, '03', '02', '04', '05')");
        Page<PickOrder> page = new Page<PickOrder>(pageNo, pageSize);
        IPage<PickOrder> pageList = pickOrderService.page(page, queryWrapper);
        return Result.OK(pageList);
    }

    /**
     * 生成货垛码
     *
     * @param
     * @return
     */
    @AutoLog(value = "理货管理-生成货垛码")
    @ApiOperation(value = "理货管理-生成货垛码", notes = "理货管理-生成货垛码")
    @PostMapping("/makeQRCode")
    public Result<?> makeQRCode() {
        String stackCode = String.valueOf(System.currentTimeMillis());
        BufferedImage bufferedImage = QRCodeUtil.produceLabel(stackCode);
        String base64Str = "";
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try {
            ImageIO.write(bufferedImage, "png", byteArrayOutputStream);
            byte[] imageBytes = byteArrayOutputStream.toByteArray();
            base64Str = Base64.getEncoder().encodeToString(imageBytes);
        } catch (Exception exception) {
            log.info("时间：{},bufferedImageToBase64方法出现异常：", LocalDateTime.now(), exception);
        }

        Map<String, String> returnMap = new HashMap<>();
        returnMap.put("stackCode", stackCode);
        returnMap.put("base64Str", base64Str);
        return Result.OK(returnMap);
    }

    /**
     * 发布理货任务
     *
     * @param pickOrderId 理货单id
     * @return
     */
    @AutoLog(value = "理货管理-发布理货任务")
    @ApiOperation(value = "理货管理-发布理货任务", notes = "理货管理-发布理货任务")
    @PostMapping("/release")
    public Result<?> release(@RequestParam(name = "id") String pickOrderId) {
        PickOrder pickOrder = pickOrderService.getById(pickOrderId);
        Assert.notNull(pickOrder, "理货单数据异常，请联系管理员！");
        Assert.isFalse(Objects.equals(pickOrder.getStatus(), WarehouseConstant.PickWarehouseTaskStaffEnum.RELEASE_END.getCode()), "理货单已发布，请勿重复操作！");
        Assert.isFalse(Objects.equals(pickOrder.getStatus(), WarehouseConstant.PickWarehouseTaskStaffEnum.DELETE.getCode()), "理货单已被删除，无法发布！");
        Assert.isTrue(Objects.equals(pickOrder.getStatus(), WarehouseConstant.PickWarehouseTaskStaffEnum.CREATE_END.getCode()), "只有创建完成的理货单才可以发布！");

        List<PickOrderDetail> pickOrderDetailList = pickOrderDetailService.list(new LambdaQueryWrapper<PickOrderDetail>()
                .eq(PickOrderDetail::getPickOrderId, pickOrderId));
        Assert.notEmpty(pickOrderDetailList, "请填写理货单详情后发布！");

        Set<String> skuCodeSet = pickOrderDetailList.stream().map(PickOrderDetail::getSkuCode).collect(Collectors.toSet());
        for (String skuCode : skuCodeSet) {
            int skuCount = basicSkuInfoService.count(new LambdaQueryWrapper<BasicSkuInfo>()
                    .eq(BasicSkuInfo::getSkuCode, skuCode)
                    .eq(BasicSkuInfo::getSkuType, pickOrder.getGoodsType()));
            Assert.isTrue(skuCount > 0,
                    "【%s】中未维护品番编码【%s】，无法发布理货单！",
                    WarehouseConstant.SkuTypeEnum.getDefineByCode(pickOrder.getGoodsType()), skuCode);
        }

        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        pickOrder.setReleaseName(sysUser.getUsername());
        pickOrder.setReleaseTime(new Date());
        pickOrder.setStatus(WarehouseConstant.PickWarehouseTaskStaffEnum.RELEASE_END.getCode());
        pickOrderService.updateById(pickOrder);
        return Result.OK();
    }

    /**
     * 领取理货任务
     *
     * @param pickOrderId 理货单id
     * @return
     */
    @AutoLog(value = "理货管理-领取理货任务")
    @ApiOperation(value = "理货管理-领取理货任务", notes = "理货管理-领取理货任务")
    @PostMapping("/receive")
    public Result<?> receive(@RequestParam(name = "id") String pickOrderId) {
        PickOrder pickOrder = pickOrderService.getById(pickOrderId);
        Assert.notNull(pickOrder, "理货单数据异常，请联系管理员！");
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        int count = pickOrderService.count(new LambdaQueryWrapper<PickOrder>()
                .eq(PickOrder::getExecuteName, sysUser.getUsername())
                .eq(PickOrder::getStatus, WarehouseConstant.PickWarehouseTaskStaffEnum.RECEIVE_END.getCode()));
        Assert.isTrue(count == 0, "您存在正在进行中的任务，无法重复领取任务！");

        pickOrder.setExecuteName(sysUser.getUsername());
        pickOrder.setExecuteTime(new Date());
        pickOrder.setStatus(WarehouseConstant.PickWarehouseTaskStaffEnum.RECEIVE_END.getCode());
        pickOrderService.updateById(pickOrder);
        return Result.OK();
    }

    /**
     * 理货任务单
     *
     * @return 任务列表，有每个货垛与对应的品番。如果后续不需要展示品番那就返回货垛码Set
     */
    @AutoLog(value = "理货管理-获取理货任务单")
    @ApiOperation(value = "理货管理-获取理货任务单", notes = "理货管理-获取理货任务单")
    @PostMapping("/getDoingTaskDetail")
    @Transactional(rollbackFor = Exception.class)
    public Result<?> getDoingTaskDetail() {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        PickOrder pickOrder = pickOrderService.getOne(new LambdaQueryWrapper<PickOrder>()
                .eq(PickOrder::getExecuteName, sysUser.getUsername())
                .eq(PickOrder::getStatus, WarehouseConstant.PickWarehouseTaskStaffEnum.RECEIVE_END.getCode()));
        Assert.notNull(pickOrder, "查询到您没有正在执行中的理货任务！");

        // 理货单详情
        List<PickOrderDetail> list = pickOrderDetailService.list(new LambdaQueryWrapper<PickOrderDetail>()
                .eq(PickOrderDetail::getPickOrderId, pickOrder.getId()));
        return Result.OK(list);
    }

    /**
     * 扫码理货
     *
     * @param pickOrderDetail pickOrderId 前端传来的理货单id(需要和后端获取的当前登录人正在执行的理货单id相同，否则就是当前登录人执行了别的理货单)
     * @param pickOrderDetail labelNumber 扫描的货垛码对应的标签号
     * @return 理货单状态, 手持页面需要根据我返回的理货状态来判断是否展示发布任务的按钮
     */
    @AutoLog(value = "理货管理-扫码理货")
    @ApiOperation(value = "理货管理-扫码理货", notes = "理货管理-扫码理货")
    @PostMapping("/scanCode")
    @Transactional(rollbackFor = Exception.class)
    public Result<?> scanCode(@RequestBody PickOrderDetail pickOrderDetail) {
        String pickOrderId = pickOrderDetail.getPickOrderId();
        String labelNumber = pickOrderDetail.getStackCode();
        Assert.isTrue(StringUtils.isNotBlank(pickOrderId), "缺少必要参数pickOrderId！");
        Assert.isTrue(StringUtils.isNotBlank(labelNumber), "缺少必要参数labelNumber！");

        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        PickOrder pickOrder = pickOrderService.getOne(new LambdaQueryWrapper<PickOrder>()
                .eq(PickOrder::getExecuteName, sysUser.getUsername())
                .eq(PickOrder::getStatus, WarehouseConstant.PickWarehouseTaskStaffEnum.RECEIVE_END.getCode()));
        Assert.notNull(pickOrder, "查询到您没有正在执行中的理货任务，无需扫码理货！");
        Assert.isTrue(Objects.equals(pickOrder.getStatus(), WarehouseConstant.PickWarehouseTaskStaffEnum.RECEIVE_END.getCode()),
                "理货单状态：【%s】，不支持拣货！", WarehouseConstant.PickWarehouseTaskStaffEnum.getDefineByCode(pickOrder.getStatus()));
        Assert.isTrue(Objects.equals(pickOrderId, pickOrder.getId()), "请勿执行他人的理货任务！");

        List<ReportLabel> checkStackCodeList = reportLabelService.list(new LambdaQueryWrapper<ReportLabel>()
                .eq(ReportLabel::getWarehouseCode, WarehouseConstant.WarehouseTypeEnum.PICK.getCode())
                .eq(ReportLabel::getInOrderCode, pickOrder.getPickOrderCode()));
        long count = checkStackCodeList.stream().filter(data -> labelNumber.contains(data.getStackCode())).count();
        Assert.isTrue(count == 0, "请勿重复扫码！");

        // 理货单详情
        List<PickOrderDetail> list = pickOrderDetailService.list(new LambdaQueryWrapper<PickOrderDetail>()
                .eq(PickOrderDetail::getPickOrderId, pickOrder.getId()));
        Assert.notEmpty(list, "理货单详情数据异常！请联系管理员");

        String checkStackCode = null;
        for (PickOrderDetail orderDetail : list) {
            if (labelNumber.contains(orderDetail.getStackCode())) {
                checkStackCode = orderDetail.getStackCode();
            }
        }
        Assert.notNull(checkStackCode, "扫描的二维码不正确！");


        // 过滤出扫码货垛的理货单详情，并按品番编码分组
        Map<String, List<PickOrderDetail>> map = list.stream()
                .filter(data -> labelNumber.contains(data.getStackCode()))
                .collect(Collectors.groupingBy(PickOrderDetail::getSkuCode));
        for (String skuCode : map.keySet()) {
            List<PickOrderDetail> pickOrderDetailList = map.get(skuCode);
            String stackCode = pickOrderDetailList.get(0).getStackCode();
            // 扫描的货垛中 这个品番的总箱数与总件数
            int boxNum = pickOrderDetailList.stream().mapToInt(PickOrderDetail::getBoxNumber).sum();
            int goodsNum = pickOrderDetailList.stream().mapToInt(PickOrderDetail::getGoodsNumber).sum();
            // report_label 理货区数据存储逻辑：以理货订单号、货垛码、品番编码作为唯一(不存储货架编码与货格编码)。
            ReportLabel reportLabel = new ReportLabel();
            reportLabel.setWarehouseCode(WarehouseConstant.WarehouseTypeEnum.PICK.getCode());
            reportLabel.setLabelNumber(labelNumber);
            reportLabel.setSkuCode(skuCode);
            reportLabel.setInventoryBoxQuantity(boxNum);
            reportLabel.setInventoryGoodsQuantity(goodsNum);
            reportLabel.setAvailableBoxQuantity(boxNum);
            reportLabel.setAvailableGoodsQuantity(goodsNum);
            reportLabel.setShelfCode("-");
            reportLabel.setCompartmentCode("-");
            reportLabel.setStackCode(stackCode);
            reportLabel.setSkuType(pickOrder.getGoodsType());
            reportLabel.setInOrderId(null);
            reportLabel.setInOrderCode(pickOrder.getPickOrderCode());
            reportLabel.setInDate(null);
            reportLabel.setStackingDate(new Date());
            reportLabel.setContainerNo(pickOrder.getContainerNo());
            reportLabel.setOutOrderId(null);
            reportLabelService.save(reportLabel);

            // inventory_info 理货区数据存储逻辑：以品番编码作为唯一(不存储货架编码、货格编码)。
            InventoryInfo inventoryInfo = inventoryInfoService.getOne(new LambdaQueryWrapper<InventoryInfo>()
                    .eq(InventoryInfo::getWarehouseCode, WarehouseConstant.WarehouseTypeEnum.PICK.getCode())
                    .eq(InventoryInfo::getSkuCode, skuCode));
            if (null == inventoryInfo) {
                inventoryInfo = new InventoryInfo();
                inventoryInfo.setWarehouseCode(WarehouseConstant.WarehouseTypeEnum.PICK.getCode());
                inventoryInfo.setShelfCode("-");
                inventoryInfo.setCompartmentCode("-");
                inventoryInfo.setStackCode(stackCode);
                inventoryInfo.setSkuCode(skuCode);
                inventoryInfo.setInventoryBoxQuantity(boxNum);
                inventoryInfo.setInventoryGoodsQuantity(goodsNum);
                inventoryInfo.setAvailableBoxQuantity(boxNum);
                inventoryInfo.setAvailableGoodsQuantity(goodsNum);
                inventoryInfo.setEnterDate(new Date());
                inventoryInfo.setOutOrderId(null);
                inventoryInfoService.save(inventoryInfo);
            } else {
                inventoryInfo.setInventoryBoxQuantity(inventoryInfo.getInventoryBoxQuantity() + boxNum);
                inventoryInfo.setInventoryGoodsQuantity(inventoryInfo.getInventoryGoodsQuantity() + goodsNum);
                inventoryInfo.setAvailableBoxQuantity(inventoryInfo.getAvailableBoxQuantity() + boxNum);
                inventoryInfo.setAvailableGoodsQuantity(inventoryInfo.getAvailableGoodsQuantity() + goodsNum);
                inventoryInfoService.updateById(inventoryInfo);
            }
        }

        // 校验理货是否完成
        Set<String> orderStackCodeSet = list.stream().map(PickOrderDetail::getStackCode).collect(Collectors.toSet());
        List<ReportLabel> reportLabelList = reportLabelService.list(new LambdaQueryWrapper<ReportLabel>()
                .eq(ReportLabel::getWarehouseCode, WarehouseConstant.WarehouseTypeEnum.PICK.getCode())
                .eq(ReportLabel::getInOrderCode, pickOrder.getPickOrderCode()));
        Set<String> reportStackCodeSet = reportLabelList.stream().map(ReportLabel::getStackCode).collect(Collectors.toSet());
        if (reportStackCodeSet.equals(orderStackCodeSet)) {
            pickOrder.setStatus(WarehouseConstant.PickWarehouseTaskStaffEnum.EXECUTE_END.getCode());
            pickOrder.setEndTime(new Date());
            pickOrderService.updateById(pickOrder);
        }

        return Result.OK(pickOrder.getStatus());
    }

    /**
     * 发布任务
     *
     * @param pickOrderId 理货单id
     * @return
     */
    @AutoLog(value = "理货管理-发布任务")
    @ApiOperation(value = "理货管理-发布任务", notes = "理货管理-发布任务")
    @PostMapping("/releaseTask")
    @Transactional(rollbackFor = Exception.class)
    public Result<?> releaseTask(@RequestParam(name = "id") String pickOrderId) {
        PickOrder pickOrder = pickOrderService.getById(pickOrderId);
        Assert.notNull(pickOrder, "理货单数据异常，请联系管理员！");
        Assert.isTrue(pickOrder.getStatus().equals(WarehouseConstant.PickWarehouseTaskStaffEnum.EXECUTE_END.getCode()), "未拣货完成的理货单无法发布任务！");
        List<PickOrderDetail> list = pickOrderDetailService.list(new LambdaQueryWrapper<PickOrderDetail>().eq(PickOrderDetail::getPickOrderId, pickOrderId));
        Assert.notEmpty(list, "理货单详情数据异常，请联系管理员！");

        // inventory_info (更新可用库存，目的：锁住库存)
        Map<String, List<PickOrderDetail>> map = list.stream().collect(Collectors.groupingBy(PickOrderDetail::getSkuCode));
        for (String skuCode : map.keySet()) {
            List<PickOrderDetail> pickOrderDetailList = map.get(skuCode);
            // 理货单内品番的总箱数与总件数
            int boxNum = pickOrderDetailList.stream().mapToInt(PickOrderDetail::getBoxNumber).sum();
            int goodsNum = pickOrderDetailList.stream().mapToInt(PickOrderDetail::getGoodsNumber).sum();
            // 库存信息
            InventoryInfo inventoryInfo = inventoryInfoService.getOne(new LambdaQueryWrapper<InventoryInfo>()
                    .eq(InventoryInfo::getWarehouseCode, WarehouseConstant.WarehouseTypeEnum.PICK.getCode())
                    .eq(InventoryInfo::getSkuCode, skuCode));
            Assert.notNull(inventoryInfo, "库存数据异常，请联系管理员！");
            Assert.isTrue(boxNum <= inventoryInfo.getAvailableBoxQuantity(),
                    "当前理货单中，品番编码【%s】共计【%s】箱，理货区内可用库存【%s】箱，理货区库存不足，无法发布入库任务！", skuCode, boxNum, inventoryInfo.getAvailableBoxQuantity());
            Assert.isTrue(goodsNum <= inventoryInfo.getAvailableGoodsQuantity(),
                    "当前理货单中，品番编码【%s】共计【%s】件，理货区内可用库存【%s】件，理货区库存不足，无法发布入库任务！", skuCode, goodsNum, inventoryInfo.getAvailableGoodsQuantity());

            inventoryInfo.setAvailableBoxQuantity(inventoryInfo.getAvailableBoxQuantity() - boxNum);
            inventoryInfo.setAvailableGoodsQuantity(inventoryInfo.getAvailableGoodsQuantity() - goodsNum);
            inventoryInfoService.updateById(inventoryInfo);
        }


        // 创建入库单
        InOrder inOrder = new InOrder();
        inOrder.setInOrderCode(pickOrder.getPickOrderCode());
        inOrder.setContainerNo(pickOrder.getContainerNo());
        inOrder.setInOrderTime(new Date());
        inOrder.setArea("-");
        inOrder.setGoodsType(pickOrder.getGoodsType());
        inOrder.setRemarks(pickOrder.getRemarks());
        inOrder.setStatus(WarehouseConstant.EnterWarehouseEnum.CREATE_END.getCode());
        inOrderService.save(inOrder);
        // 创建入库单详情
        List<InOrderDetail> inOrderDetailList = new ArrayList<>();
        for (PickOrderDetail pickOrderDetail : list) {
            InOrderDetail inOrderDetail = new InOrderDetail();
            inOrderDetail.setInOrderId(inOrder.getId());
            inOrderDetail.setStackCode(pickOrderDetail.getStackCode());
            inOrderDetail.setSkuCode(pickOrderDetail.getSkuCode());
            inOrderDetail.setBoxNumber(pickOrderDetail.getBoxNumber());
            inOrderDetail.setStatus(CommonConstant.STATUS_1);
            inOrderDetailList.add(inOrderDetail);
        }
        inOrderDetailService.saveBatch(inOrderDetailList);

        // 发布入库单
        inOrderService.releaseWarehousingEntry(inOrder.getId());

        // 更新理货状态
        pickOrder.setStatus(WarehouseConstant.PickWarehouseTaskStaffEnum.ENTER_ORDER.getCode());
        pickOrderService.updateById(pickOrder);

        return Result.OK();
    }

    /**
     * 添加
     *
     * @param pickOrderPage
     * @return
     */
    @AutoLog(value = "理货管理-添加")
    @ApiOperation(value = "理货管理-添加", notes = "理货管理-添加")
    @PostMapping(value = "/add")
    public Result<?> add(@RequestBody PickOrderPage pickOrderPage) {
        PickOrder pickOrder = new PickOrder();
        BeanUtils.copyProperties(pickOrderPage, pickOrder);
        pickOrderService.savePickOrder(pickOrder, pickOrderPage.getPickOrderDetailList());
        return Result.OK("添加成功！");
    }

    /**
     * 编辑
     *
     * @param pickOrderPage
     * @return
     */
    @AutoLog(value = "理货管理-编辑")
    @ApiOperation(value = "理货管理-编辑", notes = "理货管理-编辑")
    @PutMapping(value = "/edit")
    public Result<?> edit(@RequestBody PickOrderPage pickOrderPage) {
        PickOrder pickOrder = new PickOrder();
        BeanUtils.copyProperties(pickOrderPage, pickOrder);
        PickOrder pickOrderEntity = pickOrderService.getById(pickOrder.getId());
        if (pickOrderEntity == null) {
            return Result.error("未找到对应数据");
        }
        pickOrderService.savePickOrder(pickOrder, pickOrderPage.getPickOrderDetailList());
        return Result.OK("编辑成功!");
    }

    /**
     * 通过id删除
     *
     * @param id
     * @return
     */
    @AutoLog(value = "理货管理-通过id删除")
    @ApiOperation(value = "理货管理-通过id删除", notes = "理货管理-通过id删除")
    @DeleteMapping(value = "/delete")
    public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
        pickOrderService.delMain(id);
        return Result.OK("删除成功!");
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @AutoLog(value = "理货管理-批量删除")
    @ApiOperation(value = "理货管理-批量删除", notes = "理货管理-批量删除")
    @DeleteMapping(value = "/deleteBatch")
    public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
        this.pickOrderService.delBatchMain(Arrays.asList(ids.split(",")));
        return Result.OK("批量删除成功！");
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    @AutoLog(value = "理货管理-通过id查询")
    @ApiOperation(value = "理货管理-通过id查询", notes = "理货管理-通过id查询")
    @GetMapping(value = "/queryById")
    public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
        PickOrder pickOrder = pickOrderService.getById(id);
        if (pickOrder == null) {
            return Result.error("未找到对应数据");
        }
        return Result.OK(pickOrder);
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    @AutoLog(value = "理货单详情通过主表ID查询")
    @ApiOperation(value = "理货单详情主表ID查询", notes = "理货单详情-通主表ID查询")
    @GetMapping(value = "/queryPickOrderDetailByMainId")
    public Result<?> queryPickOrderDetailListByMainId(@RequestParam(name = "id", required = true) String id) {
        PickOrder pickOrder = pickOrderService.getById(id);
        Assert.notNull(pickOrder, "理货单数据异常，请联系管理员！");


        List<PickOrderDetail> pickOrderDetailList = pickOrderDetailService.selectByMainId(id);
        for (PickOrderDetail pickOrderDetail : pickOrderDetailList) {
            int count = reportLabelService.count(new LambdaQueryWrapper<ReportLabel>()
                    .eq(ReportLabel::getWarehouseCode, WarehouseConstant.WarehouseTypeEnum.PICK.getCode())
                    .eq(ReportLabel::getStackCode, pickOrderDetail.getStackCode())
                    .eq(ReportLabel::getInOrderCode, pickOrder.getPickOrderCode()));
            pickOrderDetail.setStatus(count > 0 ? WarehouseConstant.EnterWarehouseDetailEnum.ENTER_END.getCode() : WarehouseConstant.EnterWarehouseDetailEnum.ENTER_NOT.getCode());
        }
        pickOrderDetailList = pickOrderDetailList.stream().sorted(Comparator.comparing(PickOrderDetail::getStatus)).collect(Collectors.toList());
        return Result.OK(pickOrderDetailList);
    }

    /**
     * 导出excel
     *
     * @param request
     * @param pickOrder
     */
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(HttpServletRequest request, PickOrder pickOrder) {
        // Step.1 组装查询条件查询数据
        QueryWrapper<PickOrder> queryWrapper = QueryGenerator.initQueryWrapper(pickOrder, request.getParameterMap());
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        //Step.2 获取导出数据
        List<PickOrder> queryList = pickOrderService.list(queryWrapper);
        // 过滤选中数据
        String selections = request.getParameter("selections");
        List<PickOrder> pickOrderList = new ArrayList<PickOrder>();
        if (oConvertUtils.isEmpty(selections)) {
            pickOrderList = queryList;
        } else {
            List<String> selectionList = Arrays.asList(selections.split(","));
            pickOrderList = queryList.stream().filter(item -> selectionList.contains(item.getId())).collect(Collectors.toList());
        }

        // Step.3 组装pageList
        List<PickOrderPage> pageList = new ArrayList<PickOrderPage>();
        for (PickOrder main : pickOrderList) {
            PickOrderPage vo = new PickOrderPage();
            BeanUtils.copyProperties(main, vo);
            List<PickOrderDetail> pickOrderDetailList = pickOrderDetailService.selectByMainId(main.getId());
            vo.setPickOrderDetailList(pickOrderDetailList);
            pageList.add(vo);
        }

        // Step.4 AutoPoi 导出Excel
        ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
        mv.addObject(NormalExcelConstants.FILE_NAME, "理货管理列表");
        mv.addObject(NormalExcelConstants.CLASS, PickOrderPage.class);
        mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("理货管理数据", "导出人:" + sysUser.getRealname(), "理货管理"));
        mv.addObject(NormalExcelConstants.DATA_LIST, pageList);
        return mv;
    }

    /**
     * 通过excel导入数据
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();// 获取上传文件对象
            ImportParams params = new ImportParams();
            params.setTitleRows(2);
            params.setHeadRows(1);
            params.setNeedSave(true);
            try {
                List<PickOrderPage> list = ExcelImportUtil.importExcel(file.getInputStream(), PickOrderPage.class, params);
                for (PickOrderPage page : list) {
                    PickOrder po = new PickOrder();
                    BeanUtils.copyProperties(page, po);
                    pickOrderService.savePickOrder(po, page.getPickOrderDetailList().stream().filter(data -> StringUtils.isNotBlank(data.getStackCode()) && StringUtils.isNotBlank(data.getSkuCode())).collect(Collectors.toList()));
                }
                return Result.OK("文件导入成功！数据行数:" + list.size());
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                return Result.error("文件导入失败:" + e.getMessage());
            } finally {
                try {
                    file.getInputStream().close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return Result.OK("文件导入失败！");
    }

}
